package templates

import (
	"gitverse.ru/synapse/kubelatte/pkg/logs"
	"go.uber.org/zap"
	"testing"

	"github.com/stretchr/testify/require"
)

func TestFromYAML(t *testing.T) {
	tests := []struct {
		name    string
		yaml    string
		want    interface{}
		wantErr bool
	}{
		{
			"invalid yaml",
			"'",
			nil,
			true,
		},
		{
			"empty object",
			"{}",
			map[string]interface{}{},
			false,
		},
		{
			"raw string",
			"hello world",
			"hello world",
			false,
		},
		{
			"array of strings",
			`["hello", "goodbye"]`,
			[]interface{}{"hello", "goodbye"},
			false,
		},
		{
			"array of objects",
			`["hello", {}]`,
			[]interface{}{"hello", map[string]interface{}{}},
			false,
		},
		{
			"top-level object",
			`age: "23"
hello: bar`,
			map[string]interface{}{"age": "23", "hello": "bar"},
			false,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := FromYAML(tt.yaml)
			if tt.wantErr {
				require.Error(t, err, "Expected error unmarshalling yaml string")
				return
			}

			require.NoError(t, err, "Unexpected error unmarshalling yaml string")
			require.Equal(t, tt.want, got)
		})
	}
}

func TestToYAML(t *testing.T) {
	type args struct {
		resource interface{}
	}
	tests := []struct {
		name    string
		args    args
		want    string
		wantErr bool
	}{
		{
			name: "ok",
			args: args{resource: map[string]interface{}{"bobob": 123, "bubu": map[string]interface{}{"lolo": "pufpuf"}}},
			want: `bobob: 123
bubu:
  lolo: pufpuf
`,
			wantErr: false,
		},
		{
			name:    "empty",
			args:    args{},
			want:    "",
			wantErr: false,
		},
	}

	logs.Logger = zap.NewNop()

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := ToYAML(tt.args.resource)
			if (err != nil) != tt.wantErr {
				t.Errorf("ToYAML() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if got != tt.want {
				t.Errorf("ToYAML() got = %v, \nwant %v", []byte(got), []byte(tt.want))
			}
		})
	}
}

func TestNindent(t *testing.T) {
	type args struct {
		in        string
		spacesNum int
	}
	tests := []struct {
		name string
		args args
		want string
	}{
		{
			name: "simple",
			args: args{
				in: `some:
  yaml:
    simple:
      string`,
				spacesNum: 2,
			},
			want: `
  some:
    yaml:
      simple:
        string
`,
		},
		{
			name: "not-so-simple",
			args: args{
				in: `some:
  yaml:
    not-so-simple:
      - strings
      - strings`,
				spacesNum: 0,
			},
			want: `
some:
  yaml:
    not-so-simple:
      - strings
      - strings
`,
		},
		{
			name: "empty",
			args: args{
				in:        "",
				spacesNum: 0,
			},
			want: "\n\n",
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := Nindent(tt.args.in, tt.args.spacesNum); got != tt.want {
				t.Errorf("Nindent() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestIndent(t *testing.T) {
	type args struct {
		in        string
		spacesNum int
	}
	tests := []struct {
		name string
		args args
		want string
	}{
		{
			name: "simple",
			args: args{
				in: `some:
  yaml:
    simple:
      string`,
				spacesNum: 2,
			},
			want: `some:
    yaml:
      simple:
        string
`,
		},
		{
			name: "not-so-simple",
			args: args{
				in: `some:
  yaml:
    not-so-simple:
      - strings
      - strings`,
				spacesNum: 0,
			},
			want: `some:
  yaml:
    not-so-simple:
      - strings
      - strings
`,
		},
		{
			name: "empty",
			args: args{
				in:        "",
				spacesNum: 0,
			},
			want: "\n",
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := Indent(tt.args.in, tt.args.spacesNum); got != tt.want {
				t.Errorf("Indent() = \n%v, want \n%v", got, tt.want)
			}
		})
	}
}
